import Const from '../../../common/const';
import numeric from 'numeric';

/* eslint-disable no-magic-numbers*/
const r = 10,
    R = 13,
    a = 16,
    h = 8,
    reserve = 100;
let left = [
    [-R, a / 2],
    [-R, -a / 2],
    [-R - h, 0],
    [-r, a / 2],
    [-r, -a / 2],
    [-r + h, 0],
];
let transform = [];
for (let i = 0; i < 4; ++i) {
    let theta = Math.PI * i / 2;
    transform.push(
        [Math.cos(theta), -Math.sin(theta)], [Math.sin(theta), Math.cos(theta)]
    );
}
let POINTS = numeric.dot(transform, numeric.transpose(left));
POINTS = numeric.mul(POINTS, reserve);
POINTS = numeric.round(POINTS);
POINTS = numeric.div(POINTS, reserve);
console.table(POINTS);

export default class PassMessageMask {

    PASS_ALL = Const.Direction.MaskAll;

    directions = [
        Const.Direction.Left,
        Const.Direction.Top,
        Const.Direction.Right,
        Const.Direction.Bottom,
        Const.Direction.LeftIn,
        Const.Direction.TopIn,
        Const.Direction.RightIn,
        Const.Direction.BottomIn,
    ]

    constructor(tileMap) {
        this.tileMap = tileMap;
        this.tileWidth = tileMap.config.tileWidth;
        this.tileHeight = tileMap.config.tileHeight;
        this.canvasContext = tileMap.canvasContext;

    }

    getPass(tile) {
        return tile == null || tile.pass == null ? this.PASS_ALL : tile.pass;
    }

    draw(cell) {
        let pass = cell.tiles.reduce((p, tile) => p & this.getPass(tile), this.getPass(cell));
        //pass = Math.ceil(Math.random() * 256);
        let center = [cell.pos[0] * this.tileWidth + this.tileWidth / 2, cell.pos[1] * this.tileHeight + this.tileHeight / 2];
        //let points = POINTS.map((row, y) => row.map(e => e + center[y & 1]));
        let cx = this.canvasContext;
        cx.fillStyle = 'white';
        cx.strokeStyle = 'white';
        cx.lineWidth = 2;
        //console.log(pass);
        for (let i = 0; i < Const.Direction.Count; ++i) {
            cx.beginPath();
            cx.moveTo(POINTS[i << 1][0] + center[0], POINTS[(i << 1) + 1][0] + center[1]);
            cx.lineTo(POINTS[i << 1][1] + center[0], POINTS[(i << 1) + 1][1] + center[1]);
            cx.lineTo(POINTS[i << 1][2] + center[0], POINTS[(i << 1) + 1][2] + center[1]);
            cx.lineTo(POINTS[i << 1][0] + center[0], POINTS[(i << 1) + 1][0] + center[1]);
            if (pass & this.directions[i]) {
                cx.fill();
            } else {
                cx.stroke();
            }


            cx.beginPath();
            cx.moveTo(POINTS[i << 1][3] + center[0], POINTS[(i << 1) + 1][3] + center[1]);
            cx.lineTo(POINTS[i << 1][4] + center[0], POINTS[(i << 1) + 1][4] + center[1]);
            cx.lineTo(POINTS[i << 1][5] + center[0], POINTS[(i << 1) + 1][5] + center[1]);
            cx.lineTo(POINTS[i << 1][3] + center[0], POINTS[(i << 1) + 1][3] + center[1]);
            if (pass & this.directions[i + Const.Direction.Count]) {
                cx.fill();
            } else {
                cx.stroke();
            }
        }
    }

    onClick(cell, e) {
        let hit = this.getHitDirection(e.offsetX, e.offsetY);
        if (!hit) {
            return;
        }
        let pass = this.getPass(cell);
        if (pass & hit) {
            pass &= ~hit; 
        } else {
            pass |= hit;
        }
        cell.pass = pass;
    }

    getHitDirection(x, y) {
        let p = [
            x - this.tileWidth / 2,
            y - this.tileHeight / 2
        ];
        for (let i = 0; i < Const.Direction.Count; ++i) {
            if (this.inTrangle(p,
                    [POINTS[i << 1][0], POINTS[(i << 1) + 1][0]],
                    [POINTS[i << 1][1], POINTS[(i << 1) + 1][1]],
                    [POINTS[i << 1][2], POINTS[(i << 1) + 1][2]],
                )) {
                return this.directions[i];
            }
            if (this.inTrangle(p,
                    [POINTS[i << 1][3], POINTS[(i << 1) + 1][3]],
                    [POINTS[i << 1][4], POINTS[(i << 1) + 1][4]],
                    [POINTS[i << 1][5], POINTS[(i << 1) + 1][5]],
                )) {
                return this.directions[i + Const.Direction.Count];
            }
        }
    }

    inTrangle(p, t1, t2, t3) {
        let v1 = numeric.sub(t1, p);
        let v2 = numeric.sub(t2, p);
        let v3 = numeric.sub(t3, p);
        let s1 = numeric.det([v1, v2]);
        let s2 = numeric.det([v2, v3]);
        let s3 = numeric.det([v3, v1]);
        return s1 * s2 >= 0 && s2 * s3 >= 0 && s3 * s1 >= 0;

    }
}
